package com.aaa.sys.util;

import com.aaa.common.constants.BusinessConstant;
import com.aaa.common.entity.Dept;
import com.aaa.common.entity.OperLog;
import com.aaa.common.util.JWTUtils;
import com.aaa.sys.service.DeptService;
import com.aaa.sys.service.OperLogService;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * shiyong aop技术记录操作日志
 *
 * @author Xiujie Yu
 * @Date 2021-01-21
 * @Time 9:09
 */
@Component
@Aspect
public class OperationLogHandler {

    @Resource
    private OperLogService operaLogService;

    @Resource
    private DeptService deptService;


    /**
     * 功能描述:使用后置通知
     *
     * @param joinPoint JoinPoint
     * @return void
     */
    @Before("execution(* com.aaa.sys.service.impl.*.insert*(..))" +
            " || execution(* com.aaa.sys.service.impl.*.update*(..))" +
           " || execution(* com.aaa.sys.service.impl.*.delete*(..))" )
    public void recordOperationLog(JoinPoint joinPoint) {
        OperLog operLog = getOperLog(joinPoint);
        operaLogService.insert(operLog);
    }


    //@AfterThrowing(pointcut = "",throwing = "ex")
    public void afterException(JoinPoint joinPoint,Exception ex){
        OperLog operLog = getOperLog(joinPoint);
        operLog.setStatus(1);
        operLog.setErrorMsg(ex.getClass().getName());
        operaLogService.insert(operLog);
    }



    public OperLog getOperLog(JoinPoint joinPoint){

        OperLog operLog = new OperLog();
        operLog.setTitle("后台管理模块");
        String methodname = joinPoint.getSignature().getName();
        //删除
        int businessType = BusinessConstant.OperationLogType.DELETE;
        if(methodname.contains("insert")){
            //添加
            businessType = BusinessConstant.OperationLogType.INSERT;
        }else if (methodname.contains("update")){
            //修改
            businessType = BusinessConstant.OperationLogType.UPDATE;
        }
        operLog.setBusinessType(businessType);
        //获取目标对象 含有连接点的对象都是目标对象 切入点是多个连接点的集合 连接点是切入点表达式拦截到的所有
        String className = joinPoint.getTarget().getClass().getName();
        operLog.setMethod(className+"."+methodname);
        //设置操作类型  1为后台用户  2为手机端用户
        operLog.setOperatorType(1);

        //获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        String myAuthorization = request.getHeader("myAuthorization");
        DecodedJWT tokenPayload = JWTUtils.getTokenPayload(myAuthorization);
        String id = tokenPayload.getClaim("id").asString();
        String deptId = tokenPayload.getClaim("deptId").asString();
        String username = tokenPayload.getClaim("username").asString();
        Dept dept = deptService.queryById(Integer.parseInt(deptId));

        //设置操作人及不部门信息
        operLog.setDeptName(dept.getDeptName());
        operLog.setOperName(username);
        //获取请求的url /menu/selectOne?id=1
        String operUri = request.getRequestURI();
        // StringBuffer requestURL = request.getRequestURL(); //http://localhost:12166/menu/selectOne?id=1
        operLog.setOperUrl(operUri);
        //设置IP
        operLog.setOperIp(request.getRemoteAddr());
        //设置位置
        operLog.setOperLocation("内网IP");

        //获取请求参数   获取连接点方法的所有参数
        Object[] args = joinPoint.getArgs();
        if(args!=null&&args.length>0){
            //获取第一个参数
            String simpleName = args[0].getClass().getSimpleName();
            operLog.setOperParam(simpleName);
        }
        //设置是否有异常
        operLog.setStatus(0);
        operLog.setErrorMsg("无异常");
        //设置操作时间
        operLog.setOperTime(new Date());
        return operLog;
    }
}
